#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev.h>
#include <stdlib.h>

#include "video.h"
#include "../Socket/socket.h"
#include "../tools/CPtrList.h"

//extern	int	udpSocket;
int c_v[2][3];

#define WIDTH       768
#define HEIGHT      576
#define BYTE        unsigned char
#define mmax(a, b)    (((a) > (b)) ? (a) : (b))
#define coop 9
extern int g_ndayH ;
extern int g_ndayL ;
extern int g_chTimeH ;
extern int g_chTimeL ;


///////////////////////////////////
//CCamaraCtrl
///////////////////////////////////
void dalay(int n)
{
	static timespec ts,tr;
	ts.tv_sec = n/1000;
	ts.tv_nsec = (n%1000)*1000000;
	do
	{
		nanosleep(&ts,&tr);
		ts = tr;
	}while(tr.tv_sec != 0 || tr.tv_nsec != 0);
}
CCamaraCtrl::CCamaraCtrl()
{
	m_CamaraID[0] = 0;	//１通道摄像机号
	m_CamaraID[1] = 1;	//２通道摄像机号
	m_CamaraIP = inet_addr( "127.0.0.1" );	//摄像机控制程序IP
	m_nlLastAdjustTime = time(0)-1000;	//上次微调整时间
	m_nlLastSaveTime = time(0);	//上次保存参数时间

	m_nMaxCamaraValue = 511;
	m_nMinCamaraValue = 0;

	m_bControl = 0; 	//????
	m_nNoRecongniseNum = 0;	

	strcpy(m_fname,"/mnt/data/video0.dat");
	
	m_nPlateGray = 0;		//牌照亮度
	m_nPlateCount = 0;		//牌照个数
	m_nLastPlateGray = 0;	//上次牌照平均亮度

	m_nPlateGrayMaxTH=85;	//平均亮度上阀值
	m_nPlateGrayMinTH=75;	//平均亮度下阀值
	m_nPlateCountMaxTH=10;	//牌照个数阀值
	m_nAdjustTimeMaxTH=120;	//调整间隔

	m_nMaxVideoGray[0] = 165;
	m_nMinVideoGray[0] = 135;
	
	m_nMaxVideoGray[1] = 115;
	m_nMinVideoGray[1] = 85;
	
	m_nMaxVideoGray[2] = 215;
	m_nMinVideoGray[2] = 185;
	
	m_nLastTime = time(0);
}

///////////////////////////////////

CCamaraCtrl::~CCamaraCtrl()
{
}

void CCamaraCtrl::AdjustCamara() //3, 在合适的时机调整摄像机亮度控制参数，
{
	//printf("adjust .... count = %d\n", m_nPlateCount);
	if(m_nPlateCount>0)
	{
		int oldCamaraValue = m_nCamaraValue;
		int PlateGray = m_nPlateGray/m_nPlateCount;
		if(m_nLastPlateGray > m_nPlateGrayMaxTH && PlateGray>m_nPlateGrayMaxTH)
		{
			m_nCamaraValue-=5;
		}
		if(m_nLastPlateGray < m_nPlateGrayMinTH && PlateGray<m_nPlateGrayMinTH)
		{
			m_nCamaraValue+=5;
		}
		
		SetCamara();

		m_nLastPlateGray = PlateGray;
		m_nPlateGray=0;
		m_nPlateCount=0;
		m_nlLastAdjustTime = time(0);				
	}
	
	if(abs(time(0)-m_nlLastSaveTime)>60)
	{
		FILE * fp;
		fp = fopen( m_fname, "w" );
		if( fp != NULL )
		{
			long time0 = time(0);
			int camara=m_nCamaraValue;
			if(fwrite( &time0, sizeof(time0), 1, fp ))
			{
				fwrite( &camara, sizeof(camara), 1, fp );
			}
			fclose(fp);
			printf("*****Save camara Para %d*****\r\n",camara);
		}

		m_nlLastSaveTime = time(0);
	}	
}

void CCamaraCtrl::SetCamara()//发送摄像机控制命令：
{
	time_t OldTime = time(NULL);
	 struct tm * curtime = localtime(&OldTime);
	if(curtime->tm_hour >= g_chTimeL &&curtime->tm_hour <= g_chTimeH)
	{
		if(m_nCamaraValue<g_ndayL)
			m_nCamaraValue=g_ndayL;

	
		if(m_nCamaraValue>g_ndayH)
			m_nCamaraValue=g_ndayH;
	}
	else
	{
		if(m_nCamaraValue<m_nMinCamaraValue)
			m_nCamaraValue=m_nMinCamaraValue;

	
		if(m_nCamaraValue>m_nMaxCamaraValue)
			m_nCamaraValue=m_nMaxCamaraValue;
	}
	printf("CPR_yt: %d card %d channel set %d camara value %d\r\n",m_nVideoCardNo, m_channel, m_CamaraID[m_channel],m_nCamaraValue);
	
	if(m_nLastCamaraValue == m_nCamaraValue && abs(time(0)-m_nLastTime)<5)
	{
		printf("%d card return\n", m_nVideoCardNo);
		return;
	}	
	m_nLastTime = time(0);
	c_v[m_nVideoCardNo][1] = m_nCamaraValue;
	
	m_nLastCamaraValue = m_nCamaraValue;
	
	//printf("CPR_yt: %d card %d channel set %d camara value %d\r\n",m_nVideoCardNo, m_channel, m_CamaraID[m_channel],m_nCamaraValue);
	{
		BYTE v0[16];
		DWORD * p = (DWORD*)v0;
		p[0] = 0xf055aa0f;
		p[1] = m_CamaraID[m_channel];
		p[2] = m_nCamaraValue;
		p[3] = 0xf0aa550f;

		int len = 0;
		sockaddr_in	 addr;
		memset(&addr,0,sizeof(addr));
		addr.sin_family = AF_INET;
		addr.sin_port = htons(0x3412);
		addr.sin_addr.s_addr = m_CamaraIP;//inet_addr( g_SendOutIP )
		
		//sendto(udpSocket,v0 ,16,0,(sockaddr*)&addr,sizeof(addr));
		
		/*
		extern int		g_nRoadwayType;
		extern DWORD	g_MiddleCamaraID[2];

		if( g_nRoadwayType == 0 && m_nVideoCardNo == 1) //set middle camara with 1 camara
		{
			p[1] = g_MiddleCamaraID[m_channel];
			sendto(udpSocket,v0 ,16,0,(sockaddr*)&addr,sizeof(addr));
		}
		*/
	}
	
	return;
}

/////////////////////
//CVideo
/////////////////////
CVideo::CVideo()
{
	m_fd = -1;
	m_map = NULL;
	
	FILE* f = fopen("/proc/cpuinfo","r");
	char buf[256];
	for(int i=0;i<7;i++) fgets(buf,256,f);
	fclose(f);
	
	m_cpu_hz = atof(&buf[11]);
	
	printf("%s\n hz = %f\n",&buf[11],m_cpu_hz);

	pthread_mutex_init(&m_CaptureMutex, NULL);

	m_bRunCaptureThread = false;
	m_bQuit = true;	
	m_tmppBits = new BYTE[768*576*3];
}

CVideo::~CVideo()
{
	while(m_bRunCaptureThread)
	{
		m_bQuit = true;
		//Sleep(100);
		dalay(100);
	}

	if(m_map != NULL) munmap(m_map,2*0x208000);
	m_map = 0;
	if(m_fd >=0) close(m_fd);
	m_fd = -1;
	delete m_tmppBits;;
}
	
bool CVideo::InitVideoSystem(int nIndex,int nColorFmt,int nFieldFmt)
{
	m_Camara.m_nVideoCardNo = nIndex;
	
	if(nColorFmt != COLOR_FMT_RGB24 &&
	   nColorFmt != COLOR_FMT_YUV422 &&
	   nColorFmt != COLOR_FMT_YUV411) 
	{
		printf("InitVideoSytem(%d) : ColorFmt error.\n",nIndex);
		return false;
	}
	
	if(nFieldFmt != FIELD_FMT_ODD &&
	   nFieldFmt != FIELD_FMT_EVEN &&
	   nFieldFmt != FIELD_FMT_ALL)
	{
		printf("InitVideoSytem(%d) : FieldFmt error.\n",nIndex);
	}

	m_nColorFmt = nColorFmt;
	m_nFieldFmt = nFieldFmt;
			
	if(m_map != NULL) munmap(m_map,2*0x208000);
	m_map = NULL;
	if(m_fd >=0) close(m_fd);
	m_fd = -1;

	char name[64];
	sprintf(name,"/dev/video%d",nIndex);
	m_fd=open(name,O_RDONLY);
	if(m_fd < 0) 
	{
		//printf("m_fd < 0\n");
		return false;
	}
	
	int ver = ioctl(m_fd, BTTV_VERSION,0);
	if(ver < 0x20001)
	{
		printf("\n====================================================\n");
		printf("Bttv driver version is lower than we need.\n");
		printf("Current driver version is %05x while we need 20001\n",ver);
		printf("====================================================\n\n");
		
		close(m_fd);
		m_fd = -1;
		return false;
	}
		
	m_map=mmap(0, 2*0x208000, PROT_READ, MAP_SHARED, m_fd, 0);
	if(m_map == NULL)
	{
		close(m_fd);
		m_fd = -1;
		printf("m_map == NULL\n");
		return false;
	}
	
	for(int i=0;i<2;i++)
	{
		v[i].format=m_nColorFmt|m_nFieldFmt;//VIDEO_PALETTE_RGB24;    // ... GREY, RGB555, RGB565, RGB24, RGB32
		v[i].frame=i;                       // 0 or 1 (buffer 0 or buffer 1)
		v[i].width=768;                     // from 32 to 924 (sometimes limited to 768)
		v[i].height=576;                    // from 32 to 576
	}
	
	CaptureImage(0);
	SyncCapture(0);	
	SetChannel(0);
	
	GetVideoParam();
	
	return true;
}

bool CVideo::CaptureImage(int nBuffer)
{
	if(nBuffer < 0 || nBuffer > 1) return false;
	if(m_fd < 0) return false;
	
	if(ioctl(m_fd, VIDIOCMCAPTURE, &v[nBuffer])<0)        // start capturing a frame
		return false;
	
	return true;
}
bool CVideo::SyncCapture(int nBuffer)
{
	if(nBuffer < 0 || nBuffer > 1) return false;
	if(m_fd < 0) return false;

	if(ioctl(m_fd, VIDIOCSYNC, &v[nBuffer].frame)<0)      // wait for end of frame
		return false;
	return true;
}

void CVideo::ConvertFromYUV411(BYTE* pData,BYTE* pDib)
{
	BYTE* ps = pData;
	BYTE* pscb = ps + 768*576;
	BYTE* pscr = pscb + 768*576/4;
	
	BYTE* pd = pDib + 768*575*3;
	
	for(int j=0;j<576;j++)
	{
		if(((j & 1) == 0 && m_nFieldFmt == FIELD_FMT_EVEN) // skip odd field
		   || ((j & 1) == 1 && m_nFieldFmt == FIELD_FMT_ODD) ) // skip even field
		{
			pd -= 768*3;
			ps += 768;
			pscr += 768/4;
			pscb += 768/4;
			continue;
		}
		
		BYTE* pdd = pd;
		for(int k=0;k<768;k+=4)
		{
			for(int i=0;i<4;i++)
			{
//				int r = (int)(1.164*(*ps-16) + 1.596*(*pscr-128));
//				int g = (int)(1.164*(*ps-16) - 0.813*(*pscr-128) - 0.391*(*pscb-128));
//				int b = (int)(1.164*(*ps-16) + 2.018*(*pscb-128));

				int y = *ps;
				int yy = 1192*(y-16);
				int cr = *pscr;
				int cb = *pscb;
				
				int r = (int)(yy + 1634*(cr-128));
				int g = (int)(yy - 833*(cr-128) - 400*(cb-128));
				int b = (int)(yy + 2066*(cb-128));
				
				if(b < 0) b = 0;
				else 
				if(b > 261120) b = 255;
				else b >>= 10;
				
				if(g < 0) g = 0;
				else 
				if(g > 261120) g = 255;
				else g >>= 10;
				
				if(r < 0) r = 0;
				else
				if(r > 261120) r = 255;
				else r >>= 10;
				
				*pdd++ = b;
				*pdd++ = g;
				*pdd++ = r;
				
				ps++;
			}
			
			pscb++; pscr++;
		}	
		pd -= 768*3;
	}
}

void CVideo::ConvertFromYUV422(BYTE* pData,BYTE* pDib)
{
	BYTE* ps = pData;
	BYTE* pscb = ps + 768*576;
	BYTE* pscr = pscb + 768*576/2;
	
	BYTE* pd = pDib + 768*575*3;
	
	for(int j=0;j<576;j++)
	{
		if(((j & 1) == 0 && m_nFieldFmt == FIELD_FMT_EVEN) // skip odd field
		   || ((j & 1) == 1 && m_nFieldFmt == FIELD_FMT_ODD) ) // skip even field
		{
			pd -= 768*3;
			ps += 768;
			pscr += 768/2;
			pscb += 768/2;
			continue;
		}
		
		BYTE* pdd = pd;
		
		for(int k=0;k<768;k+=2)
		{
			for(int i=0;i<2;i++)
			{
//				int r = (int)(1.164*(*ps-16) + 1.596*(*pscr-128));
//				int g = (int)(1.164*(*ps-16) - 0.813*(*pscr-128) - 0.391*(*pscb-128));
//				int b = (int)(1.164*(*ps-16) + 2.018*(*pscb-128));

				int y = *ps;
				int yy = 1192*(y-16);
				int cr = *pscr;
				int cb = *pscb;
				
				int r = (int)(yy + 1634*(cr-128));
				int g = (int)(yy - 833*(cr-128) - 400*(cb-128));
				int b = (int)(yy + 2066*(cb-128));
				
				if(b < 0) b = 0;
				else 
				if(b > 261120) b = 255;
				else b >>= 10;
				
				if(g < 0) g = 0;
				else 
				if(g > 261120) g = 255;
				else g >>= 10;
				
				if(r < 0) r = 0;
				else
				if(r > 261120) r = 255;
				else r >>= 10;
				
				*pdd++ = b;
				*pdd++ = g;
				*pdd++ = r;
				
				ps++;
			}
			
			pscb++; pscr++;
		}
		pd -= 768*3;	
	}
}

bool CVideo::ConvertImageFormat(BYTE* ps,BYTE* pd)
{
	if(m_nColorFmt == COLOR_FMT_RGB24) return false;
	
	if(m_nColorFmt == COLOR_FMT_YUV422)
		ConvertFromYUV422(ps,pd);
	if(m_nColorFmt == COLOR_FMT_YUV411)
		ConvertFromYUV411(ps,pd);
		
	return true;
}

double CVideo::CopyImage(int nBuffer,unsigned char* pBits,bool bConvert,bool *pLostData)
{
	if(nBuffer < 0 || nBuffer > 1) return false;
	if(m_fd < 0) return false;
	if(m_map == NULL) return false;
	
	int linelen = 768*3;
	unsigned char* ps = ((unsigned char*)m_map) + nBuffer*0x208000;
	
	unsigned long long tick = *(unsigned long long*)(ps + 0x208000 - 8);
	unsigned long lostData = *(unsigned long*)(ps + 0x208000 - 12);

	if(pLostData != NULL) *pLostData = lostData;
		
	double t = tick;
	t /= m_cpu_hz*1000000;
	
	if(m_nColorFmt == COLOR_FMT_RGB24)
	{
		unsigned char* pd = pBits + linelen*575;
	
		for(int i=0;i<576;i++)
		{
			if( ((i&1)==0 && m_nFieldFmt == FIELD_FMT_EVEN) ||
			    ((i&1)==1 && m_nFieldFmt == FIELD_FMT_ODD))
			{
				// skip
			}
			else
			{
				memcpy(pd,ps,linelen);
			}
			pd -= linelen;
			ps += linelen;
		}
	}
	else
	{
		if(bConvert)
		{
			if(m_nColorFmt == COLOR_FMT_YUV422)
				ConvertFromYUV422(ps,pBits);
			if(m_nColorFmt == COLOR_FMT_YUV411)
				ConvertFromYUV411(ps,pBits);
		}
		else
		{
			unsigned char* pd = pBits;
	
				for(int i=0;i<576;i++)
				{
				if( ((i&1)==0 && m_nFieldFmt == FIELD_FMT_EVEN) ||
				    ((i&1)==1 && m_nFieldFmt == FIELD_FMT_ODD))
				{
					// skip
				}
				else
				{
					memcpy(pd,ps,linelen);
				}
				pd += linelen;
				ps += linelen;
			}
		}
	}
	
	return t;
}

void YUV2RGB(BYTE * py,BYTE * pu,BYTE * pv,BYTE * pd)
{
	BYTE * pdd = pd;
	int y = *py;
	int yy = 1192*(y-16);
	int cr = *pu;
	int cb = *pv;

	int r = (int)(yy + 1634*(cr-128));
	int g = (int)(yy - 833*(cr-128) - 400*(cb-128));
	int b = (int)(yy + 2066*(cb-128));

	if(b < 0) b = 0;
	else 
	if(b > 261120) b = 255;
	else b >>= 10;

	if(g < 0) g = 0;
	else 
	if(g > 261120) g = 255;
	else g >>= 10;

	if(r < 0) r = 0;
	else
	if(r > 261120) r = 255;
	else r >>= 10;

	*pdd++ = b;
	*pdd++ = g;
	*pdd++ = r;
}
			
double CVideo::CopyJpgImage(int nBuffer,unsigned char* pBits)
{
	if(nBuffer < 0 || nBuffer > 1) return false;
	if(m_fd < 0) return false;
	if(m_map == NULL) return false;
	
	int linelen = 768*3;
	unsigned char* ps = ((unsigned char*)m_map) + nBuffer*0x208000;
	
	unsigned long long tick = *(unsigned long long*)(ps + 0x208000 - 8);
	unsigned long lostData = *(unsigned long*)(ps + 0x208000 - 12);

	double t = tick;
	t /= m_cpu_hz*1000000;
	
	if(m_nColorFmt == COLOR_FMT_RGB24)
	{
		unsigned char* pd = pBits + 384*287*3;
		unsigned char* pss = ps;
		if (m_nFieldFmt == FIELD_FMT_ODD)
			pss+=linelen;
			
		for(int i=0;i<288;i++)
		{
			for(int j=0;j<384;j++)
			{
			*pd++=*pss++;
			*pd++=*pss++;
			*pd++=*pss++;
			pss+=3;
			}
			pd -= 768*3;
			pss += 768*3;
		}
		
	}
	else
	{
		if(m_nColorFmt == COLOR_FMT_YUV422)
			ConvertFromYUV422(ps, m_tmppBits);
		if(m_nColorFmt == COLOR_FMT_YUV411)
			ConvertFromYUV411(ps, m_tmppBits);

		unsigned char* pd = pBits;
		unsigned char* pss = m_tmppBits;
		if (m_nFieldFmt == FIELD_FMT_ODD)
			pss+=linelen;

		for(int i=0;i<288;i++)
		{
			for(int j=0;j<384;j++)
			{
			*pd++=*pss++;
			*pd++=*pss++;
			*pd++=*pss++;
			pss+=3;
			}
			pss += 768*3;
		}
	}
	return t;
}

void CVideo::SetChannel(int nIndex)
{
	if(m_fd < 0) return;
	if(m_map == NULL) return;
	
	struct video_channel ch;
	if(ioctl(m_fd,VIDIOCGCHAN,&ch) < 0)
	ch.channel = nIndex;
	strcpy(ch.name,"com1");
	ch.tuners = 0;
	ch.flags = VIDEO_VC_TUNER;
	ch.type = VIDEO_TYPE_CAMERA;
	ch.norm = 0;
	ioctl(m_fd,VIDIOCSCHAN,&ch);
	m_Camara.m_channel = nIndex;	
}

int CVideo::GetBrightness()
{
	return m_videoParam.brightness / 256;
}

int CVideo::GetContrast()
{
	return m_videoParam.contrast / 256;
}

int CVideo::GetHue()
{
	return m_videoParam.hue / 256;
}

int CVideo::GetSaturation()
{
	return m_videoParam.colour / 256;
}

void CVideo::SetBrightness(int v)
{
	if(v > 255) v = 255;
	if(v < 0) v = 0;
	
	m_videoParam.brightness = v * 256;
	SetVideoParam();
}

void CVideo::SetContrast(int v)
{
	if(v > 255) v = 255;
	if(v < 0) v = 0;
	
	m_videoParam.contrast = v * 256;
	SetVideoParam();
}

void CVideo::SetHue(int v)
{
	if(v > 255) v = 255;
	if(v < 0) v = 0;
	
	m_videoParam.hue = v * 256;
	SetVideoParam();
}

void CVideo::SetSaturation(int v)
{
	if(v > 255) v = 255;
	if(v < 0) v = 0;
	
	m_videoParam.colour = v * 256;
	SetVideoParam();
}

void CVideo::SetVideoParam()
{
	if(m_fd < 0) return;
	if(m_map == NULL) return;
	
	ioctl(m_fd,VIDIOCSPICT,&m_videoParam);
}

void CVideo::GetVideoParam()
{
	if(m_fd < 0) return;
	if(m_map == NULL) return;
	
	ioctl(m_fd,VIDIOCGPICT,&m_videoParam);
}


void CVideo::CapturePhoto(int nPos)
{
	pthread_mutex_lock( &m_CaptureMutex );
	CaptureImage(nPos);
	SyncCapture(nPos);
	pthread_mutex_unlock( &m_CaptureMutex );
}

void CVideo::InitCamara(DWORD CamaraID1,DWORD CamaraID2,DWORD CamaraIP,int nMinCamaraValue,int nMaxCamaraValue,char fname[])
{
	m_Camara.m_CamaraID[0] = CamaraID1;	//１通道摄像机号
	m_Camara.m_CamaraID[1] = CamaraID2;	//２通道摄像机号
	m_Camara.m_CamaraIP = CamaraIP;	//摄像机控制程序IP
	m_Camara.m_nlLastAdjustTime = time(0)-200;	//上次微调整时间
	m_Camara.m_nlLastSaveTime = time(0);	//上次保存参数时间

	m_Camara.m_nMaxCamaraValue = nMaxCamaraValue;
	m_Camara.m_nMinCamaraValue = nMinCamaraValue;

	m_Camara.m_bControl = 0; 	//????
	m_Camara.m_nNoRecongniseNum = 0;	

	strcpy(m_Camara.m_fname,fname);
	
	{
		FILE * fp;
		fp = fopen( m_Camara.m_fname, "r" );
		if( fp != NULL )
		{
			printf("fname != null@@@@@\n");
			long time0;
			int camara;
			if(fread( &time0, sizeof(time0), 1, fp ))
			{
				if(fread( &camara, sizeof(camara), 1, fp ))
				{
					if(abs(time(0)-time0)<300)
					{
						m_Camara.m_bControl = 2; 	//
						m_Camara.m_nNoRecongniseNum = 0;
						m_Camara.m_nCamaraValue = camara;
						printf("*****Get Saved Camara Para %d*****\r\n",camara);
						m_Camara.SetCamara();
					}
				}
			}
			fclose(fp);
		}
	}
	
	m_Camara.m_nPlateGray = 0;		//牌照亮度
	m_Camara.m_nPlateCount = 0;		//牌照个数
	m_Camara.m_nLastPlateGray = 0;	//上次牌照平均亮度

	m_Camara.m_nPlateGrayMaxTH=85;	//平均亮度上阀值
	m_Camara.m_nPlateGrayMinTH=75;	//平均亮度下阀值
	m_Camara.m_nPlateCountMaxTH=10;	//牌照个数阀值
	m_Camara.m_nAdjustTimeMaxTH=120;	//调整间隔
	m_Camara.m_nMaxNoPlateCount = 10;
	
	char value[256];
	//
/*
	if(GetProfileString("CPR","g_ndayH",value,256,"./config.ini"))
	{                                                 
		g_ndayH = atoi(value);                         
	}                                                 
	else                                               
	{                                                 
		sprintf(value,"%d",g_ndayH);                      
		PutProfileString("CPR","g_ndayH",value,256,"./config.ini");   
	}
*/
	//
	if(GetProfileString("PlateGray","low value",value,256,"./camara.ini"))
	{                                                 
		m_Camara.m_nPlateGrayMinTH = atoi(value);                         
	}                                                 
	else                                               
	{                                                 
		sprintf(value,"%d",m_Camara.m_nPlateGrayMinTH);                      
		PutProfileString("PlateGray","low value",value,"./camara.ini");   
	}
	
	if(GetProfileString("PlateGray","high value",value,256,"./camara.ini"))
	{
		m_Camara.m_nPlateGrayMaxTH = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nPlateGrayMaxTH);
		PutProfileString("PlateGray","high value",value,"./camara.ini");
	}

	if(GetProfileString("PlateGray","adjust time",value,256,"./camara.ini"))
	{
		m_Camara.m_nAdjustTimeMaxTH = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nAdjustTimeMaxTH);
		PutProfileString("PlateGray","adjust time",value,"./camara.ini");
	}

	
	if(GetProfileString("PlateGray","MaxNoPlateCount",value,256,"./camara.ini"))
	{
		m_Camara.m_nMaxNoPlateCount = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nMaxNoPlateCount);
		PutProfileString("PlateGray","MaxNoPlateCount",value,"./camara.ini");
	}
	
	if(GetProfileString("PlateGray","MaxVideoGray0",value,256,"./camara.ini"))
	{
		m_Camara.m_nMaxVideoGray[0] = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nMaxVideoGray[0]);
		PutProfileString("PlateGray","MaxVideoGray0",value,"./camara.ini");
	}
	if(GetProfileString("PlateGray","MinVideoGray0",value,256,"./camara.ini"))
	{
		m_Camara.m_nMinVideoGray[0] = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nMinVideoGray[0]);
		PutProfileString("PlateGray","MinVideoGray0",value,"./camara.ini");
	}
	if(GetProfileString("PlateGray","MaxVideoGray1",value,256,"./camara.ini"))
	{
		m_Camara.m_nMaxVideoGray[1] = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nMaxVideoGray[1]);
		PutProfileString("PlateGray","MaxVideoGray1",value,"./camara.ini");
	}
	if(GetProfileString("PlateGray","MinVideoGray1",value,256,"./camara.ini"))
	{
		m_Camara.m_nMinVideoGray[1] = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nMinVideoGray[1]);
		PutProfileString("PlateGray","MinVideoGray1",value,"./camara.ini");
	}
	if(GetProfileString("PlateGray","MaxVideoGray2",value,256,"./camara.ini"))
	{
		m_Camara.m_nMaxVideoGray[2] = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nMaxVideoGray[2]);
		PutProfileString("PlateGray","MaxVideoGray2",value,"./camara.ini");
	}
	if(GetProfileString("PlateGray","MinVideoGray2",value,256,"./camara.ini"))
	{
		m_Camara.m_nMinVideoGray[2] = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nMinVideoGray[2]);
		PutProfileString("PlateGray","MinVideoGray2",value,"./camara.ini");
	}

	if(GetProfileString("PlateGray","plate TH",value,256,"./camara.ini"))
	{
		m_Camara.m_nPlateCountMaxTH = atoi(value);
	}
	else
	{
		sprintf(value,"%d",m_Camara.m_nPlateCountMaxTH);
		PutProfileString("PlateGray","plate TH",value,"./camara.ini");
	}

	while(m_bRunCaptureThread)
	{
		m_bQuit = true;
		//Sleep(100);
		dalay(100);
	}

	{
		pthread_attr_t attr;
		pthread_attr_init( &attr );
		pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
		pthread_create( &m_CaptureThread, &attr, CaptureThread, this);
	}
}

void CVideo::ProcessPlate(int nPlateGray)//2, 识别出牌照后，保存牌照亮度值作为摄像机亮度调整依据
{
	if(m_Camara.m_bControl==0)
		return;
	
	if(nPlateGray < 0)
	{	
		m_Camara.m_nNoRecongniseNum++;
		//printf("no reg num is %d\n", m_Camara.m_nNoRecongniseNum);

	}
	else
	if(nPlateGray == 0)
	{
		//printf("gray = 0, no num =0\n");
		m_Camara.m_nNoRecongniseNum=0;
		m_Camara.m_bControl = 2;
	}
	else
	{
		//printf("gray > 0 no num = 0\n");
		m_Camara.m_nNoRecongniseNum=0;

		m_Camara.m_nPlateGray += nPlateGray;
		m_Camara.m_nPlateCount++;
		//printf("plate count is %d\n", m_Camara.m_nPlateCount);
		m_Camara.m_bControl = 2;
		if(m_Camara.m_nPlateCount>=m_Camara.m_nPlateCountMaxTH)
		{
			m_Camara.AdjustCamara();
		}
	}
}

int CVideo::CalGray(CDIB * pDib)
{
	int nWidth = pDib->m_width;
	int nHeight = pDib->m_height;

	int sum = 0;
	int count = 0;

	
	if(pDib->m_bitcount==24)
	{
		int npWidth = pDib->StorageWidth();
		BYTE * pBits = pDib->m_pBits;
		
		int j = 0;
		if(m_nFieldFmt == FIELD_FMT_EVEN)
			j = 1;
			
		for (; j < nHeight; j += 4)
		{
			BYTE *p = pBits + (nHeight-1-j) * npWidth;
				
			for (int i = 0; i < nWidth; i += 2)
			{
				sum += (*p++) + (*p++) + (*p++);
				p += 3;
				count++;
			}
		}

		return sum / count / 3;
	}
	else
		return 0;
}

void* CVideo::CaptureThread(void*pParam)
{
	CVideo * pVideo = (CVideo*)pParam;
	pVideo->m_bRunCaptureThread = true;
	pVideo->m_bQuit = false;
	
	CDIB dib;
	dib.CreateDIB(768,576,24);

	int m_nIndex = 0;	
	int nValue = 0;
	int nOldValue = 256;

	while(!pVideo->m_bQuit)
	{
		//printf("cap...\n");
		int nGrayStep = (pVideo->m_Camara.m_nMaxCamaraValue-pVideo->m_Camara.m_nMinCamaraValue + 1) / 2;
		nValue = nGrayStep+pVideo->m_Camara.m_nMinCamaraValue;

		c_v[pVideo->m_Camara.m_nVideoCardNo][0] = pVideo->m_Camara.m_bControl;
		
		while( (pVideo->m_Camara.m_bControl<=0))// && (!pVideo->m_bQuit) )
		{
			//printf("while crl is %d\n", pVideo->m_Camara.m_bControl);
			/*
			if(pVideo->m_Camara.m_nVideoCardNo == 1)
			{
				printf("1 card nValue is %d\n", nValue);
			}
			if(pVideo->m_Camara.m_nVideoCardNo == 3)
			{
				printf("3 card nValue is %d\n", nValue);
			}	
			if(pVideo->m_Camara.m_nVideoCardNo == 5)
			{
				printf("5 card nValue is %d\n", nValue);
			}
			if(pVideo->m_Camara.m_nVideoCardNo == 7)
			{
				printf("7 card nValue is %d\n", nValue);
			}
			*/
			pVideo->m_Camara.m_nCamaraValue = nValue;
			//printf("value is %d  ", nValue);
			pVideo->m_Camara.SetCamara( );
			//Sleep(500);
			//dalay(500);
			//sleep(1);
			Sleep(1000000);
			
			//摄像机初始化第一步，按全图灰度调整
			pVideo->CapturePhoto(1);

			double ftime111  = pVideo->CopyImage(1,dib.m_pBits);
			int nGray = pVideo->CalGray(&dib);
			printf("ngray is %d\n", nGray);
			if (nGray > pVideo->m_Camara.m_nMaxVideoGray[m_nIndex])
			{
				if(pVideo->m_Camara.m_nCamaraValue<=pVideo->m_Camara.m_nMinCamaraValue)
				{
					if(pVideo->m_Camara.m_bControl<=1)
					{
						if(pVideo->m_Camara.m_nVideoCardNo == 1)
						{
							printf("1 card 1 if\n");
						}
						if(pVideo->m_Camara.m_nVideoCardNo == 3)
						{
							printf("3 card 1 if\n");
						}
						if(pVideo->m_Camara.m_nVideoCardNo == 7)
						{
							printf("7 card 1 if\n");
						}
						if(pVideo->m_Camara.m_nVideoCardNo == 5)
						{
							printf("5 card 1 if\n");
						}
					
						nValue = pVideo->m_Camara.m_nCamaraValue;
						pVideo->m_Camara.m_bControl = 1;
					}
					
					break;
				}
				
				nGrayStep = (nGrayStep + 1) / 2;

				if (nGrayStep <= 0)
					nGrayStep = 1;
			
				nValue  = pVideo->m_Camara.m_nCamaraValue - nGrayStep;
			}
			
			else if (nGray < pVideo->m_Camara.m_nMinVideoGray[m_nIndex])
			{
				if(pVideo->m_Camara.m_nCamaraValue>=pVideo->m_Camara.m_nMaxCamaraValue)
				{
					if(pVideo->m_Camara.m_bControl<=1)
					{
						if(pVideo->m_Camara.m_nVideoCardNo == 7)
						{
							printf("7 card 2 if\n");
						}
						if(pVideo->m_Camara.m_nVideoCardNo == 5)
						{
							printf("5 card 2 if \n");
						}
						if(pVideo->m_Camara.m_nVideoCardNo == 3)
						{
							printf("3 card 2 if\n");
						}
						if(pVideo->m_Camara.m_nVideoCardNo == 1)
						{
							printf("1 card 2 if \n");
						}
						nValue = pVideo->m_Camara.m_nCamaraValue;
						pVideo->m_Camara.m_bControl = 1;
					}
					break;
				}
				
				nGrayStep = (nGrayStep + 1) / 2;

				if (nGrayStep <= 0)
					nGrayStep = 1;
			
				nValue  = pVideo->m_Camara.m_nCamaraValue + nGrayStep;
			}
			
			else
			{
				if(pVideo->m_Camara.m_bControl<=1)
				{
					if(pVideo->m_Camara.m_nVideoCardNo == 7)
					{
						printf("7 card 3 if is %d\n", nValue);
					}
					if(pVideo->m_Camara.m_nVideoCardNo == 5)
					{
						printf("5 card 3 if is %d\n", nValue);
					}	
					if(pVideo->m_Camara.m_nVideoCardNo == 3)
					{
						printf("3 card 3 if is %d\n", nValue);
					}
					if(pVideo->m_Camara.m_nVideoCardNo == 1)
					{
						printf("1 card 3 if is %d\n", nValue);
					}	
					nValue = pVideo->m_Camara.m_nCamaraValue;
					pVideo->m_Camara.m_bControl = 1;
					
				}
				
				//break;
			}
			
			pVideo->m_Camara.m_nNoRecongniseNum=0;
			pVideo->m_Camara.m_nPlateGray = 0;
			pVideo->m_Camara.m_nPlateCount = 0;

		}
/*
		if(pVideo->m_Camara.m_bControl==0)
		{
			if(pVideo->m_Camara.m_nVideoCardNo == 7)
			{
				printf("7 card ctl is 0\n");
			}
			if(pVideo->m_Camara.m_nVideoCardNo == 5)
			{
				printf("5 card ctl is 0\n");
			}
			if(pVideo->m_Camara.m_nVideoCardNo == 3)
			{
				printf("3 card ctl is 0\n");
			}
			if(pVideo->m_Camara.m_nVideoCardNo == 1)
			{
				printf("1 card ctl is 0\n");
			}
		}
		*/
		//printf("cap ctl is %d\n", pVideo->m_Camara.m_bControl);
		if(pVideo->m_Camara.m_bControl==1)
		{/*
			if(pVideo->m_Camara.m_nVideoCardNo == 7)
			{
				printf("7 card ctl is 1\n");
			}
			if(pVideo->m_Camara.m_nVideoCardNo == 5)
			{
				printf("5 card ctl is 1\n");
			}
			if(pVideo->m_Camara.m_nVideoCardNo == 3)
			{
				printf("3 card ctl is 1\n");
			}
			if(pVideo->m_Camara.m_nVideoCardNo == 1)
			{
				printf("1 card ctl is 1\n");
			}
		*/
		
			if(pVideo->m_Camara.m_nNoRecongniseNum>(2*pVideo->m_Camara.m_nMaxNoPlateCount) )
			{
				//printf("ctl = 1 no num > 2*max\n");
				pVideo->m_Camara.m_nNoRecongniseNum = 0;
				m_nIndex++;
				m_nIndex%=3;
				pVideo->m_Camara.m_bControl=0;
				c_v[pVideo->m_Camara.m_nVideoCardNo][2] = m_nIndex;
				continue;
			}
		}

		if(pVideo->m_Camara.m_bControl>=2)
		{
			if(abs(time(0)-pVideo->m_Camara.m_nlLastAdjustTime)>pVideo->m_Camara.m_nAdjustTimeMaxTH)
			{
				//printf("ctl = 2 time to adj\n");
				pVideo->m_Camara.AdjustCamara();
			}
			
			if(pVideo->m_Camara.m_nNoRecongniseNum>pVideo->m_Camara.m_nMaxNoPlateCount)
			{
				//printf("no reg > max to adj\n");
				pVideo->m_Camara.m_bControl = 0;
				pVideo->m_Camara.AdjustCamara();
				continue;
			}
			else
			{
				//printf("no num is %d max is %d\n",pVideo->m_Camara.m_nNoRecongniseNum,pVideo->m_Camara.m_nMaxNoPlateCount);
			}
		}
		
		//Sleep(300);
		//sleep(1);
		Sleep(1000000);
		//dalay(300);
	}
	//printf("out of while@@@@@@@@@");

	pVideo->m_bRunCaptureThread = false;
}
